<!DOCTYPE html>



  


<html class="theme-next gemini use-motion" lang="zh-Hans">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />







<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=5.1.2" rel="stylesheet" type="text/css" />


  <meta name="keywords" content="Hexo, NexT" />





  <link rel="alternate" href="/atom.xml" title="OBKoro1's Blog" type="application/atom+xml" />




  <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=5.1.2" />






<meta name="description" content="前言在本篇文章之前，WebSocket很多人听说过，没见过，没用过，以为是个很高大上的技术，实际上这个技术并不神秘，可以说是个很容易就能掌握的技术，希望在看完本文之后，马上把文中的栗子拿出来自己试一试，实践出真知。">
<meta property="og:type" content="article">
<meta property="og:title" content="手摸手教你使用WebSocket[其实WebSocket也不难]">
<meta property="og:url" content="http://yoursite.com/2018/10/23/手摸手教你使用WebSocket-其实WebSocket也不难/index.html">
<meta property="og:site_name" content="OBKoro1&#39;s Blog">
<meta property="og:description" content="前言在本篇文章之前，WebSocket很多人听说过，没见过，没用过，以为是个很高大上的技术，实际上这个技术并不神秘，可以说是个很容易就能掌握的技术，希望在看完本文之后，马上把文中的栗子拿出来自己试一试，实践出真知。">
<meta property="og:locale" content="zh-Hans">
<meta property="og:image" content="https://github.com/OBKoro1/articleImg_src/blob/master/weibo_img_move/005Y4rColy1fwhfykkrenj30w00k075m.jpg?raw=true">
<meta property="og:updated_time" content="2019-07-20T06:55:39.066Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="手摸手教你使用WebSocket[其实WebSocket也不难]">
<meta name="twitter:description" content="前言在本篇文章之前，WebSocket很多人听说过，没见过，没用过，以为是个很高大上的技术，实际上这个技术并不神秘，可以说是个很容易就能掌握的技术，希望在看完本文之后，马上把文中的栗子拿出来自己试一试，实践出真知。">
<meta name="twitter:image" content="https://github.com/OBKoro1/articleImg_src/blob/master/weibo_img_move/005Y4rColy1fwhfykkrenj30w00k075m.jpg?raw=true">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Gemini',
    version: '5.1.2',
    sidebar: {"position":"left","display":"post","offset":12,"offset_float":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://yoursite.com/2018/10/23/手摸手教你使用WebSocket-其实WebSocket也不难/"/>





  <title>手摸手教你使用WebSocket[其实WebSocket也不难] | OBKoro1's Blog</title>
  





  <script type="text/javascript">
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?64d57d0b926bbd27431daa89d2e0a76b";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>




</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/"  class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">OBKoro1's Blog</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-前端算法">
          <a href="/arithmetic/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-book"></i> <br />
            
            前端算法
          </a>
        </li>
      
        
        <li class="menu-item menu-item-博客最新更新">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            博客最新更新
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br />
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
            
            标签
          </a>
        </li>
      
        
        <li class="menu-item menu-item-commonweal">
          <a href="/404/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-heartbeat"></i> <br />
            
            公益404
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2018/10/23/手摸手教你使用WebSocket-其实WebSocket也不难/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="OBKoro1">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/uploads/hand1.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="OBKoro1's Blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">手摸手教你使用WebSocket[其实WebSocket也不难]</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-10-23T00:22:40+08:00">
                2018-10-23
              </time>
            

            

            
          </span>

          

          
            
          

          
          
             <span id="/2018/10/23/手摸手教你使用WebSocket-其实WebSocket也不难/" class="leancloud_visitors" data-flag-title="手摸手教你使用WebSocket[其实WebSocket也不难]">
               <span class="post-meta-divider">|</span>
               <span class="post-meta-item-icon">
                 <i class="fa fa-eye"></i>
               </span>
               
                 <span class="post-meta-item-text">阅读次数&#58;</span>
               
                 <span class="leancloud-visitors-count"></span>
             </span>
          

          

          
            <div class="post-wordcount">
              
                
                <span class="post-meta-item-icon">
                  <i class="fa fa-file-word-o"></i>
                </span>
                
                  <span class="post-meta-item-text">字数统计&#58;</span>
                
                <span title="字数统计">
                  2,473 字
                </span>
              

              
                <span class="post-meta-divider">|</span>
              

              
                <span class="post-meta-item-icon">
                  <i class="fa fa-clock-o"></i>
                </span>
                
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                
                <span title="阅读时长">
                  10分钟
                </span>
              
            </div>
          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <p><img src="https://github.com/OBKoro1/articleImg_src/blob/master/weibo_img_move/005Y4rColy1fwhfykkrenj30w00k075m.jpg?raw=true" alt=""></p>
<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>在本篇文章之前，<code>WebSocket</code>很多人听说过，没见过，没用过，以为是个很高大上的技术，实际上这个技术并不神秘，可以说是个很容易就能掌握的技术，希望在看完本文之后，马上把文中的栗子拿出来自己试一试，实践出真知。</p>
<a id="more"></a>
<blockquote>
<p>游泳、健身了解一下：<a href="http://obkoro1.com/" target="_blank" rel="noopener">博客</a>、<a href="http://obkoro1.com/web_accumulate/accumulate/" target="_blank" rel="noopener">前端积累文档</a>、<a href="https://raw.githubusercontent.com/OBKoro1/articleImg_src/master/juejin/1631b6f52f7e7015.jpeg?raw=true" target="_blank" rel="noopener">公众号</a>、<a href="https://github.com/OBKoro1" target="_blank" rel="noopener">GitHub</a></p>
</blockquote>
<h3 id="WebSocket解决了什么问题："><a href="#WebSocket解决了什么问题：" class="headerlink" title="WebSocket解决了什么问题："></a><code>WebSocket</code>解决了什么问题：</h3><p>客户端(浏览器)和服务器端进行通信，只能由客户端发起<code>ajax</code>请求，才能进行通信，服务器端无法主动向客户端推送信息。</p>
<p>当出现类似体育赛事、聊天室、实时位置之类的场景时，客户端要获取服务器端的变化，就只能通过轮询(定时请求)来了解服务器端有没有新的信息变化。</p>
<blockquote>
<p>轮询效率低，非常浪费资源(需要不断发送请求，不停链接服务器)</p>
</blockquote>
<p><strong>WebSocket的出现，让服务器端可以主动向服务器端发送信息，使得浏览器具备了实时双向通信的能力,这就是<code>WebSocket</code>解决的问题</strong></p>
<h3 id="一个超简单的栗子："><a href="#一个超简单的栗子：" class="headerlink" title="一个超简单的栗子："></a>一个超简单的栗子：</h3><p><strong>新建一个<code>html</code>文件，将本栗子找个地方跑一下试试，即可轻松入门<code>WebSocket</code>：</strong></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">socketConnect</span>(<span class="params">url</span>) </span>&#123;</span><br><span class="line">    <span class="comment">// 客户端与服务器进行连接</span></span><br><span class="line">    <span class="keyword">let</span> ws = <span class="keyword">new</span> WebSocket(url); <span class="comment">// 返回`WebSocket`对象，赋值给变量ws</span></span><br><span class="line">    <span class="comment">// 连接成功回调</span></span><br><span class="line">    ws.onopen = <span class="function"><span class="params">e</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">'连接成功'</span>, e)</span><br><span class="line">        ws.send(<span class="string">'我发送消息给服务端'</span>); <span class="comment">// 客户端与服务器端通信</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 监听服务器端返回的信息</span></span><br><span class="line">    ws.onmessage = <span class="function"><span class="params">e</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">'服务器端返回：'</span>, e.data)</span><br><span class="line">        <span class="comment">// do something</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> ws; <span class="comment">// 返回websocket对象</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> wsValue = socketConnect(<span class="string">'ws://121.40.165.18:8800'</span>); <span class="comment">// websocket对象</span></span><br></pre></td></tr></table></figure>
<p>上述栗子中<code>WebSocket</code>的接口地址出自：<a href="http://www.blue-zero.com/WebSocket/" target="_blank" rel="noopener">WebSocket 在线测试</a>，在开发的时候也可以用于测试后端给的地址是否可用。</p>
<h3 id="webSocket的class类："><a href="#webSocket的class类：" class="headerlink" title="webSocket的class类："></a>webSocket的class类：</h3><p>当项目中很多地方使用WebSocket，把它封成一个class类，是更好的选择。</p>
<p><strong>下面的栗子，做了非常详细的注释，建个html文件也可直接使用</strong>，websocket的常用<code>API</code>都放进去了。</p>
<p><strong>下方注释的代码，先不用管，涉及到心跳机制，用于保持WebSocket连接的</strong></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">WebSocketClass</span> </span>&#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * @description: 初始化实例属性，保存参数</span></span><br><span class="line"><span class="comment">     * @param &#123;String&#125; url ws的接口</span></span><br><span class="line"><span class="comment">     * @param &#123;Function&#125; msgCallback 服务器信息的回调传数据给函数</span></span><br><span class="line"><span class="comment">     * @param &#123;String&#125; name 可选值 用于区分ws，用于debugger</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">constructor</span>(url, msgCallback, name = 'default') &#123;</span><br><span class="line">        <span class="keyword">this</span>.url = url;</span><br><span class="line">        <span class="keyword">this</span>.msgCallback = msgCallback;</span><br><span class="line">        <span class="keyword">this</span>.name = name;</span><br><span class="line">        <span class="keyword">this</span>.ws = <span class="literal">null</span>;  <span class="comment">// websocket对象</span></span><br><span class="line">        <span class="keyword">this</span>.status = <span class="literal">null</span>; <span class="comment">// websocket是否关闭</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * @description: 初始化 连接websocket或重连webSocket时调用</span></span><br><span class="line"><span class="comment">     * @param &#123;*&#125; 可选值 要传的数据</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    connect(data) &#123;</span><br><span class="line">        <span class="comment">// 新建 WebSocket 实例</span></span><br><span class="line">        <span class="keyword">this</span>.ws = <span class="keyword">new</span> WebSocket(<span class="keyword">this</span>.url);</span><br><span class="line">        <span class="keyword">this</span>.ws.onopen = <span class="function"><span class="params">e</span> =&gt;</span> &#123;</span><br><span class="line">            <span class="comment">// 连接ws成功回调</span></span><br><span class="line">            <span class="keyword">this</span>.status = <span class="string">'open'</span>;</span><br><span class="line">            <span class="built_in">console</span>.log(<span class="string">`<span class="subst">$&#123;<span class="keyword">this</span>.name&#125;</span>连接成功`</span>, e)</span><br><span class="line">            <span class="comment">// this.heartCheck();</span></span><br><span class="line">            <span class="keyword">if</span> (data !== <span class="literal">undefined</span>) &#123;</span><br><span class="line">                <span class="comment">// 有要传的数据,就发给后端</span></span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">this</span>.ws.send(data);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 监听服务器端返回的信息</span></span><br><span class="line">        <span class="keyword">this</span>.ws.onmessage = <span class="function"><span class="params">e</span> =&gt;</span> &#123;</span><br><span class="line">            <span class="comment">// 把数据传给回调函数，并执行回调</span></span><br><span class="line">            <span class="comment">// if (e.data === 'pong') &#123;</span></span><br><span class="line">            <span class="comment">//     this.pingPong = 'pong'; // 服务器端返回pong,修改pingPong的状态</span></span><br><span class="line">            <span class="comment">// &#125;</span></span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">this</span>.msgCallback(e.data);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// ws关闭回调</span></span><br><span class="line">        <span class="keyword">this</span>.ws.onclose = <span class="function"><span class="params">e</span> =&gt;</span> &#123;</span><br><span class="line">            <span class="keyword">this</span>.closeHandle(e); <span class="comment">// 判断是否关闭</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// ws出错回调</span></span><br><span class="line">        <span class="keyword">this</span>.onerror = <span class="function"><span class="params">e</span> =&gt;</span> &#123;</span><br><span class="line">            <span class="keyword">this</span>.closeHandle(e); <span class="comment">// 判断是否关闭</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// heartCheck() &#123;</span></span><br><span class="line">    <span class="comment">//     // 心跳机制的时间可以自己与后端约定</span></span><br><span class="line">    <span class="comment">//     this.pingPong = 'ping'; // ws的心跳机制状态值</span></span><br><span class="line">    <span class="comment">//     this.pingInterval = setInterval(() =&gt; &#123;</span></span><br><span class="line">    <span class="comment">//         if (this.ws.readyState === 1) &#123;</span></span><br><span class="line">    <span class="comment">//             // 检查ws为链接状态 才可发送</span></span><br><span class="line">    <span class="comment">//             this.ws.send('ping'); // 客户端发送ping</span></span><br><span class="line">    <span class="comment">//         &#125;</span></span><br><span class="line">    <span class="comment">//     &#125;, 10000)</span></span><br><span class="line">    <span class="comment">//     this.pongInterval = setInterval(() =&gt; &#123;</span></span><br><span class="line">    <span class="comment">//         this.pingPong = false;</span></span><br><span class="line">    <span class="comment">//         if (this.pingPong === 'ping') &#123;</span></span><br><span class="line">    <span class="comment">//             this.closeHandle('pingPong没有改变为pong'); // 没有返回pong 重启webSocket</span></span><br><span class="line">    <span class="comment">//         &#125;</span></span><br><span class="line">    <span class="comment">//         // 重置为ping 若下一次 ping 发送失败 或者pong返回失败(pingPong不会改成pong)，将重启</span></span><br><span class="line">    <span class="comment">//         console.log('返回pong')</span></span><br><span class="line">    <span class="comment">//         this.pingPong = 'ping'</span></span><br><span class="line">    <span class="comment">//     &#125;, 20000)</span></span><br><span class="line">    <span class="comment">// &#125;</span></span><br><span class="line">    <span class="comment">// 发送信息给服务器</span></span><br><span class="line">    sendHandle(data) &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">`<span class="subst">$&#123;<span class="keyword">this</span>.name&#125;</span>发送消息给服务器:`</span>, data)</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>.ws.send(data);</span><br><span class="line">    &#125;</span><br><span class="line">    closeHandle(e = <span class="string">'err'</span>) &#123;</span><br><span class="line">        <span class="comment">// 因为webSocket并不稳定，规定只能手动关闭(调closeMyself方法)，否则就重连</span></span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">this</span>.status !== <span class="string">'close'</span>) &#123;</span><br><span class="line">            <span class="built_in">console</span>.log(<span class="string">`<span class="subst">$&#123;<span class="keyword">this</span>.name&#125;</span>断开，重连websocket`</span>, e)</span><br><span class="line">            <span class="comment">// if (this.pingInterval !== undefined &amp;&amp; this.pongInterval !== undefined) &#123;</span></span><br><span class="line">            <span class="comment">//     // 清除定时器</span></span><br><span class="line">            <span class="comment">//     clearInterval(this.pingInterval);</span></span><br><span class="line">            <span class="comment">//     clearInterval(this.pongInterval);</span></span><br><span class="line">            <span class="comment">// &#125;</span></span><br><span class="line">            <span class="keyword">this</span>.connect(); <span class="comment">// 重连</span></span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="built_in">console</span>.log(<span class="string">`<span class="subst">$&#123;<span class="keyword">this</span>.name&#125;</span>websocket手动关闭`</span>)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 手动关闭WebSocket</span></span><br><span class="line">    closeMyself() &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">`关闭<span class="subst">$&#123;<span class="keyword">this</span>.name&#125;</span>`</span>)</span><br><span class="line">        <span class="keyword">this</span>.status = <span class="string">'close'</span>;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>.ws.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">someFn</span>(<span class="params">data</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">'接收服务器消息的回调：'</span>, data);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// const wsValue = new WebSocketClass('ws://121.40.165.18:8800', someFn, 'wsName'); // 这个链接一天只能发送消息50次</span></span><br><span class="line"><span class="keyword">const</span> wsValue = <span class="keyword">new</span> WebSocketClass(<span class="string">'wss://echo.websocket.org'</span>, someFn, <span class="string">'wsName'</span>); <span class="comment">// 阮一峰老师教程链接</span></span><br><span class="line">wsValue.connect(<span class="string">'立即与服务器通信'</span>); <span class="comment">// 连接服务器</span></span><br><span class="line"><span class="comment">// setTimeout(() =&gt; &#123;</span></span><br><span class="line"><span class="comment">//     wsValue.sendHandle('传消息给服务器')</span></span><br><span class="line"><span class="comment">// &#125;, 1000);</span></span><br><span class="line"><span class="comment">// setTimeout(() =&gt; &#123;</span></span><br><span class="line"><span class="comment">//     wsValue.closeMyself(); // 关闭ws</span></span><br><span class="line"><span class="comment">// &#125;, 10000)</span></span><br></pre></td></tr></table></figure>
<p>栗子里面我直接写在了一起，可以把<code>class</code>放在一个js文件里面,<code>export</code>出去，然后在需要用的地方再<code>import</code>进来，把参数传进去就可以用了。</p>
<h2 id="WebSocket不稳定"><a href="#WebSocket不稳定" class="headerlink" title="WebSocket不稳定"></a>WebSocket不稳定</h2><p>WebSocket并不稳定，在使用一段时间后，可能会断开连接，貌似至今没有一个为何会断开连接的公论，所以我们需要让WebSocket保持连接状态，这里推荐两种方法。</p>
<h3 id="WebSocket设置变量，判断是否手动关闭连接："><a href="#WebSocket设置变量，判断是否手动关闭连接：" class="headerlink" title="WebSocket设置变量，判断是否手动关闭连接："></a>WebSocket设置变量，判断是否手动关闭连接：</h3><p><strong><code>class</code>类中就是用的这种方式</strong>:设置一个变量，在webSocket关闭/报错的回调中，判断是不是手动关闭的，如果不是的话，就重新连接，这样做的优缺点如下：</p>
<ul>
<li>优点：请求较少(相对于心跳连接)，易设置。</li>
<li>缺点：可能会导致丢失数据,在断开重连的这段时间中，恰好双方正在通信。</li>
</ul>
<h3 id="WebSocket心跳机制："><a href="#WebSocket心跳机制：" class="headerlink" title="WebSocket心跳机制："></a>WebSocket心跳机制：</h3><blockquote>
<p>因为第一种方案的缺点，并且可能会有其他一些未知情况导致断开连接而没有触发Error或Close事件。这样就导致实际连接已经断开了，而客户端和服务端却不知道，还在傻傻的等着消息来。</p>
</blockquote>
<p>然后聪明的程序猿们想出了一种叫做<strong>心跳机制</strong>的解决方法：</p>
<p>客户端就像心跳一样每隔固定的时间发送一次<code>ping</code>，来告诉服务器，我还活着，而服务器也会返回<code>pong</code>，来告诉客户端，服务器还活着。</p>
<p><strong>具体的实现方法，在上面<code>class</code>的注释中，将其打开，即可看到效果</strong>。 </p>
<h2 id="关于WebSocket"><a href="#关于WebSocket" class="headerlink" title="关于WebSocket"></a>关于WebSocket</h2><p>怕一开始就堆太多文字性的内容，把各位吓跑了，现在大家已经会用了，我们再回头来看看WebSocket的其他知识点。</p>
<h3 id="WebSocket的当前状态-WebSocket-readyState"><a href="#WebSocket的当前状态-WebSocket-readyState" class="headerlink" title="WebSocket的当前状态:WebSocket.readyState"></a>WebSocket的当前状态:<code>WebSocket.readyState</code></h3><p>下面是<code>WebSocket.readyState</code>的四个值(四种状态)：</p>
<ul>
<li>0: 表示正在连接</li>
<li>1: 表示连接成功，可以通信了</li>
<li>2: 表示连接正在关闭</li>
<li>3: 表示连接已经关闭，或者打开连接失败</li>
</ul>
<p>我们可以利用当前状态来做一些事情，比如上面栗子中当WebSocket链接成功后，才允许客户端发送<code>ping</code>。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (<span class="keyword">this</span>.ws.readyState === <span class="number">1</span>) &#123;</span><br><span class="line">    <span class="comment">// 检查ws为链接状态 才可发送</span></span><br><span class="line">    <span class="keyword">this</span>.ws.send(<span class="string">'ping'</span>); <span class="comment">// 客户端发送ping</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="WebSocket还可以发送-接收-二进制数据"><a href="#WebSocket还可以发送-接收-二进制数据" class="headerlink" title="WebSocket还可以发送/接收 二进制数据"></a><code>WebSocket</code>还可以发送/接收 二进制数据</h3><p>这里我也没有试过，我是看阮一峰老师的<a href="http://www.ruanyifeng.com/blog/2017/05/websocket.html" target="_blank" rel="noopener">WebSocket教程</a>才知道有这么个东西，有兴趣的可以再去谷歌，大家知道一下就可以。</p>
<p>二进制数据包括：<code>blob</code>对象和<code>Arraybuffer</code>对象，所以我们需要分开来处理。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">    <span class="comment">// 接收数据</span></span><br><span class="line">ws.onmessage = <span class="function"><span class="keyword">function</span>(<span class="params">event</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(event.data <span class="keyword">instanceof</span> <span class="built_in">ArrayBuffer</span>)&#123;</span><br><span class="line">        <span class="comment">// 判断 ArrayBuffer 对象</span></span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span>(event.data <span class="keyword">instanceof</span> Blob)&#123;</span><br><span class="line">        <span class="comment">// 判断 Blob 对象</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 发送 Blob 对象的例子</span></span><br><span class="line"><span class="keyword">let</span> file = <span class="built_in">document</span>.querySelector(<span class="string">'input[type="file"]'</span>).files[<span class="number">0</span>];</span><br><span class="line">ws.send(file);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 发送 ArrayBuffer 对象的例子</span></span><br><span class="line"><span class="keyword">var</span> img = canvas_context.getImageData(<span class="number">0</span>, <span class="number">0</span>, <span class="number">400</span>, <span class="number">320</span>);</span><br><span class="line"><span class="keyword">var</span> binary = <span class="keyword">new</span> <span class="built_in">Uint8Array</span>(img.data.length);</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i &lt; img.data.length; i++) &#123;</span><br><span class="line">    binary[i] = img.data[i];</span><br><span class="line">&#125;</span><br><span class="line">ws.send(binary.buffer);</span><br></pre></td></tr></table></figure>
<p><strong>如果你要发送的二进制数据很大的话，如何判断发送完毕：</strong></p>
<p><code>webSocket.bufferedAmount</code>属性，表示还有多少字节的二进制数据没有发送出去：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> data = <span class="keyword">new</span> <span class="built_in">ArrayBuffer</span>(<span class="number">10000000</span>);</span><br><span class="line">socket.send(data);</span><br><span class="line"><span class="keyword">if</span> (socket.bufferedAmount === <span class="number">0</span>) &#123;</span><br><span class="line">    <span class="comment">// 发送完毕</span></span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="comment">// 发送还没结束</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>上述栗子出自阮一峰老师的<a href="http://www.ruanyifeng.com/blog/2017/05/websocket.html" target="_blank" rel="noopener">WebSocket教程</a></p>
<h3 id="WebSocket的优点："><a href="#WebSocket的优点：" class="headerlink" title="WebSocket的优点："></a>WebSocket的优点：</h3><p>最后再吹一波WebSocket：</p>
<ol>
<li>双向通信(一开始说的，也是最重要的一点)。</li>
<li><p>数据格式比较轻量，性能开销小，通信高效</p>
<p> 协议控制的数据包头部较小，而HTTP协议每次通信都需要携带完整的头部</p>
</li>
<li><p>更好的二进制支持</p>
</li>
<li>没有同源限制，客户端可以与任意服务器通信</li>
<li>与 HTTP 协议有着良好的兼容性。默认端口也是80和443，并且握手阶段采用 HTTP 协议，因此握手时不容易屏蔽，能通过各种 HTTP 代理服务器</li>
</ol>
<hr>
<h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>看了本文之后，如果还是有点迷糊的话，一定要把文中的两个栗子，新建个html文件跑起来，自己鼓捣鼓捣一下。不然读多少博客/教程都没有用，实践才出真知，切勿纸上谈兵。</p>
<h3 id="希望看完的朋友可以点个喜欢-关注，您的支持是对我最大的鼓励。"><a href="#希望看完的朋友可以点个喜欢-关注，您的支持是对我最大的鼓励。" class="headerlink" title="希望看完的朋友可以点个喜欢/关注，您的支持是对我最大的鼓励。"></a>希望看完的朋友可以点个喜欢/关注，您的支持是对我最大的鼓励。</h3><p><a href="http://obkoro1.com/" target="_blank" rel="noopener">博客</a>、<a href="http://obkoro1.com/web_accumulate/accumulate/" target="_blank" rel="noopener">前端积累文档</a>、<a href="https://raw.githubusercontent.com/OBKoro1/articleImg_src/master/juejin/1631b6f52f7e7015.jpeg?raw=true" target="_blank" rel="noopener">公众号</a>、<a href="https://github.com/OBKoro1" target="_blank" rel="noopener">GitHub</a></p>
<p> 以上2018.10.22</p>
<p> 参考资料：</p>
<p> <a href="http://www.ruanyifeng.com/blog/2017/05/websocket.html" target="_blank" rel="noopener">WebSocket 教程</a></p>
<p> <a href="https://www.cnblogs.com/tugenhua0707/p/8648044.html" target="_blank" rel="noopener">理解WebSocket心跳及重连机制</a></p>
<p> <a href="https://www.cnblogs.com/chyingp/p/websocket-deep-in.html" target="_blank" rel="noopener">WebSocket协议：5分钟从入门到精通</a></p>

      
    </div>
    
    
    

    

    
      <div>
        <div style="padding: 10px 0; margin: 20px auto; width: 90%; text-align: center;">
  <div>听说，打赏我的人最后都找到了真爱。</div>
  <button id="rewardButton" disable="enable" onclick="var qr = document.getElementById('QR'); if (qr.style.display === 'none') {qr.style.display='block';} else {qr.style.display='none'}">
    <span>打赏</span>
  </button>
  <div id="QR" style="display: none;">

    
      <div id="wechat" style="display: inline-block">
        <img id="wechat_qr" src="/images/pay/weixin.jpg" alt="OBKoro1 微信支付"/>
        <p>微信支付</p>
      </div>
    

    
      <div id="alipay" style="display: inline-block">
        <img id="alipay_qr" src="/images/pay/ali.jpg" alt="OBKoro1 支付宝"/>
        <p>支付宝</p>
      </div>
    

    

  </div>
</div>

      </div>
    

    

    <footer class="post-footer">
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2018/10/17/算法-两个字符串是变位词/" rel="next" title="算法_两个字符串是变位词">
                <i class="fa fa-chevron-left"></i> 算法_两个字符串是变位词
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2018/10/27/算法-第一次只出现一次的字符/" rel="prev" title="算法_第一次只出现一次的字符">
                算法_第一次只出现一次的字符 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          
  <div class="comments" id="comments">
    
  </div>


        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap" >
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
          
            <img class="site-author-image" itemprop="image"
              src="/uploads/hand1.jpg"
              alt="OBKoro1" />
          
            <p class="site-author-name" itemprop="name">OBKoro1</p>
            <p class="site-description motion-element" itemprop="description">种一棵树最好的时间是十年前,其次是现在</p>
        </div>

        <nav class="site-state motion-element">

          
            <div class="site-state-item site-state-posts">
            
              <a href="/archives">
            
                <span class="site-state-item-count">105</span>
                <span class="site-state-item-name">日志</span>
              </a>
            </div>
          

          
            
            
            <div class="site-state-item site-state-categories">
              <a href="/categories/index.html">
                <span class="site-state-item-count">20</span>
                <span class="site-state-item-name">分类</span>
              </a>
            </div>
          

          
            
            
            <div class="site-state-item site-state-tags">
              <a href="/tags/index.html">
                <span class="site-state-item-count">74</span>
                <span class="site-state-item-name">标签</span>
              </a>
            </div>
          

        </nav>

        
          <div class="feed-link motion-element">
            <a href="/atom.xml" rel="alternate">
              <i class="fa fa-rss"></i>
              RSS
            </a>
          </div>
        

        <div class="links-of-author motion-element">
          
            
              <span class="links-of-author-item">
                <a href="https://github.com/OBKoro1" target="_blank" title="GitHub">
                  
                    <i class="fa fa-fw fa-github"></i>GitHub</a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://juejin.im/user/58714f0eb123db4a2eb95372" target="_blank" title="掘金">
                  
                    <i class="fa fa-fw fa-globe"></i>掘金</a>
              </span>
            
              <span class="links-of-author-item">
                <a href="http://obkoro1.com/web_accumulate/" target="_blank" title="前端积累">
                  
                    <i class="fa fa-fw fa-globe"></i>前端积累</a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://segmentfault.com/u/obkoro1/articles" target="_blank" title="segmentfault">
                  
                    <i class="fa fa-fw fa-globe"></i>segmentfault</a>
              </span>
            
          
        </div>

        
        

        
        

        


      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#前言"><span class="nav-number">1.</span> <span class="nav-text">前言</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#WebSocket解决了什么问题："><span class="nav-number">1.1.</span> <span class="nav-text">WebSocket解决了什么问题：</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#一个超简单的栗子："><span class="nav-number">1.2.</span> <span class="nav-text">一个超简单的栗子：</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#webSocket的class类："><span class="nav-number">1.3.</span> <span class="nav-text">webSocket的class类：</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#WebSocket不稳定"><span class="nav-number">2.</span> <span class="nav-text">WebSocket不稳定</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#WebSocket设置变量，判断是否手动关闭连接："><span class="nav-number">2.1.</span> <span class="nav-text">WebSocket设置变量，判断是否手动关闭连接：</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#WebSocket心跳机制："><span class="nav-number">2.2.</span> <span class="nav-text">WebSocket心跳机制：</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#关于WebSocket"><span class="nav-number">3.</span> <span class="nav-text">关于WebSocket</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#WebSocket的当前状态-WebSocket-readyState"><span class="nav-number">3.1.</span> <span class="nav-text">WebSocket的当前状态:WebSocket.readyState</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#WebSocket还可以发送-接收-二进制数据"><span class="nav-number">3.2.</span> <span class="nav-text">WebSocket还可以发送/接收 二进制数据</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#WebSocket的优点："><span class="nav-number">3.3.</span> <span class="nav-text">WebSocket的优点：</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#结语"><span class="nav-number">4.</span> <span class="nav-text">结语</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#希望看完的朋友可以点个喜欢-关注，您的支持是对我最大的鼓励。"><span class="nav-number">4.1.</span> <span class="nav-text">希望看完的朋友可以点个喜欢/关注，您的支持是对我最大的鼓励。</span></a></li></ol></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright" >
  
  &copy;  2017 &mdash; 
  <span itemprop="copyrightYear">2019</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">OBKoro1</span>

  
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-area-chart"></i>
    </span>
    
      <span class="post-meta-item-text">Site words total count&#58;</span>
    
    <span title="Site words total count">
      156.0k
    </span>
  
</div>




<div>
<script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<span class="site-uv"><i class="fa fa-user"></i> 访问用户： <span class="busuanzi-value" id="busuanzi_value_site_uv">21621</span> 人 </span>
<span class="site-pv"><i class="fa fa-eye"></i> 访问次数： <span class="busuanzi-value" id="busuanzi_value_site_pv">68503</span> 次</span>

</div>



        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  


  











  
  <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>

  
  <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>

  
  <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>

  
  <script type="text/javascript" src="/lib/canvas-nest/canvas-nest.min.js"></script>


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.2"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.2"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.1.2"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.2"></script>



  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.2"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.2"></script>


  

  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.2"></script>



  


  




	





  





  








  



  





  

  
  <script src="https://cdn1.lncld.net/static/js/av-core-mini-0.6.4.js"></script>
  <script>AV.initialize("9ANFp60h6oVyxIPGlau3NOA4-gzGzoHsz", "tMdNuKMbFtN4QsekeNVu83TV");</script>
  <script>
    function showTime(Counter) {
      var query = new AV.Query(Counter);
      var entries = [];
      var $visitors = $(".leancloud_visitors");

      $visitors.each(function () {
        entries.push( $(this).attr("id").trim() );
      });

      query.containedIn('url', entries);
      query.find()
        .done(function (results) {
          var COUNT_CONTAINER_REF = '.leancloud-visitors-count';

          if (results.length === 0) {
            $visitors.find(COUNT_CONTAINER_REF).text(0);
            return;
          }

          for (var i = 0; i < results.length; i++) {
            var item = results[i];
            var url = item.get('url');
            var time = item.get('time');
            var element = document.getElementById(url);

            $(element).find(COUNT_CONTAINER_REF).text(time);
          }
          for(var i = 0; i < entries.length; i++) {
            var url = entries[i];
            var element = document.getElementById(url);
            var countSpan = $(element).find(COUNT_CONTAINER_REF);
            if( countSpan.text() == '') {
              countSpan.text(0);
            }
          }
        })
        .fail(function (object, error) {
          console.log("Error: " + error.code + " " + error.message);
        });
    }

    function addCount(Counter) {
      var $visitors = $(".leancloud_visitors");
      var url = $visitors.attr('id').trim();
      var title = $visitors.attr('data-flag-title').trim();
      var query = new AV.Query(Counter);

      query.equalTo("url", url);
      query.find({
        success: function(results) {
          if (results.length > 0) {
            var counter = results[0];
            counter.fetchWhenSave(true);
            counter.increment("time");
            counter.save(null, {
              success: function(counter) {
                var $element = $(document.getElementById(url));
                $element.find('.leancloud-visitors-count').text(counter.get('time'));
              },
              error: function(counter, error) {
                console.log('Failed to save Visitor num, with error message: ' + error.message);
              }
            });
          } else {
            var newcounter = new Counter();
            /* Set ACL */
            var acl = new AV.ACL();
            acl.setPublicReadAccess(true);
            acl.setPublicWriteAccess(true);
            newcounter.setACL(acl);
            /* End Set ACL */
            newcounter.set("title", title);
            newcounter.set("url", url);
            newcounter.set("time", 1);
            newcounter.save(null, {
              success: function(newcounter) {
                var $element = $(document.getElementById(url));
                $element.find('.leancloud-visitors-count').text(newcounter.get('time'));
              },
              error: function(newcounter, error) {
                console.log('Failed to create');
              }
            });
          }
        },
        error: function(error) {
          console.log('Error:' + error.code + " " + error.message);
        }
      });
    }

    $(function() {
      var Counter = AV.Object.extend("Counter");
      if ($('.leancloud_visitors').length == 1) {
        addCount(Counter);
      } else if ($('.post-title-link').length > 1) {
        showTime(Counter);
      }
    });
  </script>



  

  

  

  

  

</body>
</html>

